package com.itheima.a05;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;

import java.io.IOException;
import java.util.Set;

public class AtBeanTwo_2PostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
        try {
            String basePackage = "com.itheima.a05";

            String path = "classpath*:" + basePackage.replace(".", "/") + "/**/*.class";
            System.out.println(path);
            CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
            Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
            AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
            for (Resource resource : resources) {
                // System.out.println(resource);
                MetadataReader reader = factory.getMetadataReader(resource);
                // System.out.println("类名:" + reader.getClassMetadata().getClassName());
                AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
                // System.out.println("是否加了 @Component:" + annotationMetadata.hasAnnotation(Component.class.getName()));
                // System.out.println("是否加了 @Component 派生:" + annotationMetadata.hasMetaAnnotation(Component.class.getName()));
                if (annotationMetadata.hasAnnotation(Configuration.class.getName())
                        || annotationMetadata.hasMetaAnnotation(Configuration.class.getName())) {

                    //CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
                    MetadataReader confiRreader = factory.getMetadataReader(resource);


//                    String className = confiRreader.getClassMetadata().getClassName();
//                    String factoryBeanName = className.substring(className.lastIndexOf(".")+1);
//                    String firstChar = factoryBeanName.substring(0, 1);
//                    factoryBeanName = firstChar.toLowerCase()+factoryBeanName.substring(1);
                    //先将@Configuration 标注的类，注册为BeanDefinition
                    AbstractBeanDefinition bdConfig = BeanDefinitionBuilder
                            .genericBeanDefinition(reader.getClassMetadata().getClassName())
                            .getBeanDefinition();
                    String factoryBeanName = generator.generateBeanName(bdConfig, beanFactory);
                    beanFactory.registerBeanDefinition(factoryBeanName, bdConfig);


                    Set<MethodMetadata> methods = confiRreader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
                    for (MethodMetadata method : methods) {
                        System.out.println(method);
                        String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
                        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
                        builder.setFactoryMethodOnBean(method.getMethodName(), factoryBeanName);
                        builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
                        if (initMethod.length() > 0) {
                            builder.setInitMethodName(initMethod);
                        }
                        AbstractBeanDefinition bd = builder.getBeanDefinition();
                        beanFactory.registerBeanDefinition(method.getMethodName(), bd);
                    }

                }
            }




        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
